/*
 * $id$
 */

#ifndef _XP_NET_DNS_H_
#define _XP_NET_DNS_H_

#include <xp/types.h>
#include <xp/macros.h>
#include <xp/net/socket.h>

/* qr flag */
enum
{
	XP_DNS_QUERY    = 0,
	XP_DNS_RESPONSE = 1
};

/* query type */
enum
{
	XP_DNS_QUERY_A     = 1,
	XP_DNS_QUERY_NS    = 2,
	XP_DNS_QUERY_CNAME = 5,
	XP_DNS_QUERY_SOA   = 6,
	XP_DNS_QUERY_PTR   = 12,
	XP_DNS_QUERY_HINFO = 13,
	XP_DNS_QUERY_MX    = 15,
	XP_DNS_QUERY_AAAA  = 28,
	XP_DNS_QUERY_AXFR  = 252,
	XP_DNS_QUERY_ANY   = 255
};

/* opcode flag */
enum
{
	XP_DNS_OPCODE_STANDARD = 0,
	XP_DNS_OPCODE_INVERSE  = 1,
	XP_DNS_OPCODE_STATUS   = 2
};

/* rcode flag */
enum
{
	XP_DNS_RCODE_NOERROR        = 0,
	XP_DNS_RCODE_FORMATERROR    = 1,
	XP_DNS_RCODE_SERVERERROR    = 2,
	XP_DNS_RCODE_NAMEERROR      = 3,
	XP_DNS_RCODE_NOTIMPLEMENTED = 4,
	XP_DNS_RCODE_SERVICEREFUSED = 5,
};

struct xp_dns_header_t
{
	xp_uint16_t id;

#if 0
#ifdef XP_ENDIAN_BIG
	struct {
		/* 0 query, 1 response */
		xp_uint16_t qr: 1; 
		/* 0 standard query, 1 inverse query,
		 * 2 server status request, 3-15 reserved */
		xp_uint16_t opcode: 4;
		xp_uint16_t aa: 1; /* authoritative answer */
		xp_uint16_t tc: 1; /* truncation */
		xp_uint16_t rd: 1; /* recursion desired */
		xp_uint16_t ra: 1; /* resursion available */
		xp_uint16_t z: 3; /* reserved */
		xp_uint16_t rcode: 4; /* response code */
	} flags;
#else
	struct {
		xp_uint16_t rcode: 4;
		xp_uint16_t z: 3;
		xp_uint16_t ra: 1;
		xp_uint16_t rd: 1;
		xp_uint16_t tc: 1;
		xp_uint16_t aa: 1;
		xp_uint16_t opcode: 4;
		xp_uint16_t qr: 1; 
	} flags;
#endif
#endif
	xp_uint16_t flags;
	xp_uint16_t qncount; /* number of questions */
	xp_uint16_t ancount; /* number of answers(RRs) */
	xp_uint16_t nscount; /* number of authority RRs */
	xp_uint16_t arcount; /* number of additional RRs */
};
typedef struct xp_dns_header_t xp_dns_header_t;

struct xp_dns_answer_t
{
	xp_uint16_t name;
	xp_uint16_t type; // 1-"A", 5-"CNAME", 12-"PTR", 15-"MX"
	xp_uint16_t clas; // 1-"IN", 2-"CS", 3-"CH", 4-"HS"
	xp_uint32_t ttl;
	xp_uint16_t rrlen;
	/* followed by rrdata; ->string of octets, variable length*/
};
typedef struct xp_dns_answer_t xp_dns_answer_t;

struct xp_dns_t
{
	xp_sckhnd_t handle;
	xp_size_t count;
	xp_bool_t __dynamic;
};

typedef struct xp_dns_t xp_dns_t;

#ifdef __cplusplus
extern "C" {
#endif

xp_dns_t* xp_dns_open (xp_dns_t* dns);
int xp_dns_close (xp_dns_t* dns);
int xp_dns_query_a (xp_dns_t* dns, const xp_char_t* name);

#ifdef __cplusplus
}
#endif

#endif
